﻿
// MFC_FTP_ClientDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "MFC_FTP_Client.h"
#include "MFC_FTP_ClientDlg.h"
#include "afxdialogex.h"
#include "winnls.h"
#include <strsafe.h>

#include <string>             //for Test1

#define  FTP_FUNCTIONS_BUFFER_SIZE          MAX_PATH+8
#define  FTP_DIRECT_BY_WINAPI				1          //不用MFC，直接用WINAPI访问FTP

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CMFCFTPClientDlg 对话框



CMFCFTPClientDlg::CMFCFTPClientDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_MFC_FTP_CLIENT_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMFCFTPClientDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LISTBox, m_LB_IPList);
	DDX_Control(pDX, IDC_BN_Connect, m_BN_Connect);
	DDX_Control(pDX, IDC_BN_Upload, m_BN_Upload);
	DDX_Control(pDX, IDC_BN_Delete, m_BN_Delete);
	DDX_Control(pDX, IDC_BN_Download, m_BN_Download);
	DDX_Control(pDX, IDC_ET_IPInput, m_ET_IPInput);
}

BEGIN_MESSAGE_MAP(CMFCFTPClientDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_EN_CHANGE(IDC_ET_IPInput, &CMFCFTPClientDlg::OnChangeEtIpinput)
	ON_BN_CLICKED(IDC_BN_Connect, &CMFCFTPClientDlg::OnClickedBnConnect)
	ON_BN_CLICKED(IDC_BN_Delete, &CMFCFTPClientDlg::OnClickedBnDelete)
	ON_BN_CLICKED(IDC_BN_Download, &CMFCFTPClientDlg::OnClickedBnDownload)
	ON_BN_CLICKED(IDC_BN_Upload, &CMFCFTPClientDlg::OnClickedBnUpload)
	ON_LBN_SELCHANGE(IDC_LISTBox, &CMFCFTPClientDlg::OnSelchangeListbox)
	ON_BN_CLICKED(IDC_BN_Test, &CMFCFTPClientDlg::OnBnClickedBnTest)
	ON_BN_CLICKED(IDOK, &CMFCFTPClientDlg::OnBnClickedOk)
	ON_BN_CLICKED(IDC_BN_TEST1, &CMFCFTPClientDlg::OnBnClickedBnTest1)
	ON_BN_CLICKED(IDC_BN_Test2, &CMFCFTPClientDlg::OnBnClickedBnTest2)
END_MESSAGE_MAP()


// CMFCFTPClientDlg 消息处理程序

BOOL CMFCFTPClientDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	SetDlgItemText(IDC_ET_IPInput, _T("localhost")); 
	
	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void CMFCFTPClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CMFCFTPClientDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFCFTPClientDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CMFCFTPClientDlg::OnChangeEtIpinput()
{
	// TODO:  如果该控件是 RICHEDIT 控件，它将不
	// 发送此通知，除非重写 CDialogEx::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask()，
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

	// TODO:  在此添加控件通知处理程序代码
}


void CMFCFTPClientDlg::OnClickedBnConnect()
{
	// TODO: 在此添加控件通知处理程序代码
	CString strAdress;
	GetDlgItemText(IDC_ET_IPInput, strAdress);

	//CString m_IPadress
	CString strUser;
	CString strPass;
	strPass = "123456";//密码
	strUser = "sjc";//用户名

	try {
			m_pInetSession = new CInternetSession(AfxGetAppName(), 1, PRE_CONFIG_INTERNET_ACCESS);
			m_pFtpConnection = m_pInetSession->GetFtpConnection(strAdress, strUser, strPass);
			m_pRemoteFile = new CFtpFileFind(m_pFtpConnection);
		}
		catch (CInternetException* e) {
			// Log the exception
			DWORD_PTR dwContext = e->m_dwContext;
			DWORD dwError = e->m_dwError;
			e->Delete();
		}
	this->RefreshWithRemote();
}

void CMFCFTPClientDlg::OnClickedBnDelete()
{
	// TODO: 在此添加控件通知处理程序代码
	CString strSelFile;
	m_LB_IPList.GetText(m_LB_IPList.GetCurSel(), strSelFile);
	if (!strSelFile.IsEmpty())
	{
#ifdef _UNICODE
		if (AfxMessageBox(L"确定要删除这个文件吗？", 4 + 48) == 6)
#endif // _UNICODE
#ifdef _MBCS
		if (AfxMessageBox("确定要删除这个文件吗？", 4 + 48) == 6)
#endif // _MBCS

		{
			m_pFtpConnection->Remove(strSelFile);
		}
		CString strDir;
		m_pFtpConnection->GetCurrentDirectory(strDir);
		m_pInetSession->Close();
		this->OnClickedBnConnect();
		m_pFtpConnection->SetCurrentDirectory(strDir);	
	}
	this->RefreshWithRemote();
}


void CMFCFTPClientDlg::OnClickedBnDownload()
{
	// TODO: 在此添加控件通知处理程序代码
	CString strSelFile;
	m_LB_IPList.GetText(m_LB_IPList.GetCurSel(), strSelFile);
	if (!strSelFile.IsEmpty())
	{
		CFileDialog file(FALSE, NULL, strSelFile, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("所有文件(*.*)|*.*|"), this);
		//CFileDialog file(FALSE, NULL, strSelFile, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "所有文件(*.*)|*.*|", this);
		if (file.DoModal() == IDOK)
		{
			CString strname;
			//strname = file.GetFileName();
			strname = file.GetPathName();
			CString strDir;
			m_pFtpConnection->GetCurrentDirectory(strDir);
			m_pFtpConnection->GetFile(strSelFile, strname);
			m_pInetSession->Close();
			this->OnClickedBnConnect();
			m_pFtpConnection->SetCurrentDirectory(strDir);
			this->RefreshWithRemote();
			AfxMessageBox(_T("下载成功!"));
		}
	}
}


void CMFCFTPClientDlg::OnClickedBnUpload()
{
	// TODO: 在此添加控件通知处理程序代码
	CString strPath;
	CString strName;
	CFileDialog file(true, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("所有文件(*.*)|*.*|"), this);
	//CFileDialog file(true, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "所有文件(*.*)|*.*|", this);
	if (file.DoModal() == IDOK)
	{
		strPath = file.GetPathName();
		strName = file.GetFileName();

	}

	CString strDir;
	m_pFtpConnection->GetCurrentDirectory(strDir);
	BOOL bput = m_pFtpConnection->PutFile((LPCTSTR)strPath, (LPCTSTR)strName);
	if (bput)
	{
		m_pInetSession->Close();
		this->OnClickedBnConnect();
		m_pFtpConnection->SetCurrentDirectory(strDir);
		this->RefreshWithRemote();
		AfxMessageBox(_T("上传成功!"));
	}
}


void CMFCFTPClientDlg::OnSelchangeListbox()
{
	// TODO: 在此添加控件通知处理程序代码
	// 根据当前选中内容，操作并同步远程FTP服务器端内容 - 后续改为双击操作
	// 步骤一：获取当前选中内容
	CString strSelFile;
	m_LB_IPList.GetText(m_LB_IPList.GetCurSel(), strSelFile);
	//查看编码
	dump_memory("strSelFile", strSelFile.GetBuffer(), strSelFile.GetLength()+1);

	// 步骤二：判断是否为目录
	CFtpFileFind ftpfind(m_pFtpConnection);
	CString strDirPath;

	/*if (strSelFile == "..")
	{
		m_pFtpConnection->SetCurrentDirectory(_T(".."));
		this->RefreshWithRemote();
	}*/

	if ((strSelFile.Find(_T("/")) == 0)||(strSelFile == ".."))           //首字符为"/"的是目录,".."代表上级目录  .find返回找到字符的序号，找不到返回-1
	{
		// 步骤三：如果是目录，则将之替换为远程服务器的当前目录，重联刷新
	//	m_pFtpConnection->GetCurrentDirectory(strDirPath);
		
		if ((strSelFile.Find(_T("/")) == 0))
		{
			strSelFile.Delete(0, 1);      //去除首字符"/"，以相对路径设置当前目录
		}
		ANSItoUTF8(strSelFile);
		//转码后查看编码
		dump_memory("strSelFile_UTF8", strSelFile.GetBuffer(), strSelFile.GetLength()+1);
		
		DWORD	dwError;
		BOOL	retVal = FALSE;

		retVal = m_pFtpConnection->SetCurrentDirectoryA(strSelFile);
			
		if (retVal == FALSE)
		{
			dwError = GetLastError();
		/*	if (dwError == ERROR_NO_MORE_FILES)
			{
				StringCchCopy(szMsgBuffer, FTP_FUNCTIONS_BUFFER_SIZE,
					TEXT("No files found at FTP location specified."));
				retVal = TRUE;
				goto DisplayDirError_1;
			}
			StringCchCopy(szMsgBuffer, FTP_FUNCTIONS_BUFFER_SIZE,
				TEXT("FtpFindFirstFile failed."));
			goto DisplayDirError_1;*/
		}

		this->RefreshWithRemote(); 
	}
}


// 同步远程FTP服务器端内容
int CMFCFTPClientDlg::RefreshWithRemote()
{
	// TODO: 在此处添加实现代码.
	m_LB_IPList.ResetContent();
	CFtpFileFind ftpfind(m_pFtpConnection);
	CString strDirPath;  		//文件名的MBCS版本
	CStringA strAPath;

	UINT uAcp = GetACP();   //返回936 -  ANSI/OEM 简体中文 (中国、新加坡) ;简体中文 (GB2312)
	BOOL bWndUc = IsWindowUnicode(this->m_hWnd);   //返回1 - 窗口是本机 Unicode 窗口。为零时表示该窗口是本机 ANSI 窗口。
		
	m_pFtpConnection->GetCurrentDirectory(strDirPath);

	dump_memory("strDirPath_UTF8", strDirPath.GetBuffer(), strDirPath.GetLength() + 1);

	//直接用winapi操作来回避下面MFC库函数调用的问题  - start
	#ifdef FTP_DIRECT_BY_WINAPI
	{
		if (m_pFtpConnection != NULL)
		{
			// 获取句柄
			//HINTERNET hFtpSession = m_pFtpConnection->GetSession();
			//HINTERNET hFtpSession = m_pFtpConnection;
			//CInternetConnection::operator HINTERNET 是一个类型转换操作符，它允许你将 CInternetConnection 对象转换为它的底层 HINTERNET
			//句柄。HINTERNET 是一个指向WININET API中的一个数据类型的句柄，这些API用于网络通信。这个操作符通常在你需要直接使用
			// WinInet API时使用，例如当你需要传递一个 CInternetConnection 对象的句柄给一个WinInet API函数时。
			HINTERNET hFtpSession = *m_pFtpConnection;
		
			if (hFtpSession != NULL)
			{
				// 使用hFtpSession进行更底层的操作，例如直接FTP命令
				// 例如，使用Win32 API函数InternetGetFile来下载文件
				// 使用FtpGetCurrentDirectory 和 FtpSetCurrentDirectory在目录间导航
				// 使用FtpFindFirstFile 和 InternetFindNextFile进行目录枚举
				// 参考文档：https://learn.microsoft.com/zh-cn/windows/win32/wininet/ftp-sessions

				WIN32_FIND_DATA dirInfo;
				HINTERNET       hFind;
				DWORD           dwError;
				BOOL            retVal = FALSE;
				TCHAR           szMsgBuffer[FTP_FUNCTIONS_BUFFER_SIZE];
				TCHAR           szFName[FTP_FUNCTIONS_BUFFER_SIZE];
				DWORD			dwFindFlags = INTERNET_FLAG_RELOAD;

				hFind = FtpFindFirstFile(hFtpSession, strDirPath,&dirInfo, dwFindFlags, 0);
				if (hFind == NULL)
				{
					dwError = GetLastError();
					if (dwError == ERROR_NO_MORE_FILES)
					{
					/*	StringCchCopy(szMsgBuffer, FTP_FUNCTIONS_BUFFER_SIZE,TEXT("No files found at FTP location specified."));
						retVal = TRUE;
						goto DisplayDirError_1;*/
						if (strDirPath != "/")
						{
							m_LB_IPList.AddString(_T(".."));
						}
						InternetCloseHandle(hFind);
						return(TRUE);
					}
					StringCchCopy(szMsgBuffer, FTP_FUNCTIONS_BUFFER_SIZE,TEXT("FtpFindFirstFile failed."));
					goto DisplayDirError_1;
				}

				if (strDirPath != "/")
				{
					m_LB_IPList.AddString(_T(".."));
				}

				do
				{
					if (FAILED(StringCchCopy(szFName, FTP_FUNCTIONS_BUFFER_SIZE,dirInfo.cFileName)))        //拷贝文件名
					{
						StringCchCopy(szMsgBuffer, FTP_FUNCTIONS_BUFFER_SIZE,TEXT("Failed to copy a file or directory name."));
						retVal = FALSE;
						goto DisplayDirError_2;

					}
					strAPath = szFName;
					UTF8toANSI(strAPath);
					if (dirInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
					{
						strAPath = _T("/") + strAPath;
					}
					m_LB_IPList.AddString(strAPath);
				} while (InternetFindNextFile(hFind, (LPVOID)&dirInfo));

				if ((dwError = GetLastError()) == ERROR_NO_MORE_FILES)
				{
					InternetCloseHandle(hFind);
					return(TRUE);
				}
				StringCchCopy(szMsgBuffer, FTP_FUNCTIONS_BUFFER_SIZE,
					TEXT("FtpFindNextFile failed."));

			DisplayDirError_2:
				InternetCloseHandle(hFind);
			DisplayDirError_1:
				AfxMessageBox((LPCTSTR)szMsgBuffer);


			}
		}
		//直接用winapi操作来回避下面MFC库函数调用的问题  - end
	}
	#else
	{
		BOOL bfind = ftpfind.FindFile(strDirPath);

		//若为路径中含某些特殊中文字符组合，如“夹”、“新建文件夹”，则报错。参考https://bbs.csdn.net/topics/391844331中的情况，判断是MFC库的问题。可尝试直接调WINAPI看看是否可以 

		if (strDirPath != "/")
		{
			m_LB_IPList.AddString(_T(".."));
		}

		while (bfind)
		{
			bfind = ftpfind.FindNextFile();
		
			if (ftpfind.IsDots())
			{
				m_LB_IPList.AddString(_T(".."));
			//	continue;
			}
			if (!ftpfind.IsDirectory())
			{
				strAPath = ftpfind.GetFileName();
				UTF8toANSI(strAPath);
				m_LB_IPList.AddString(strAPath);
			}
			else
			{
				strAPath = ftpfind.GetFilePath();
				UTF8toANSI(strAPath);
				m_LB_IPList.AddString(strAPath);
			}
		}
		ftpfind.Close();
	}
	#endif

	return 0;
}

wchar_t* ANSIToUnicode(CStringA strANSI)
{
	int textlen;
	wchar_t* result;
	UINT uAcp = GetACP();
	const char* strTemp = strANSI;
	textlen = MultiByteToWideChar(uAcp, 0, strTemp, -1, NULL, 0);
	result = (wchar_t*)malloc((textlen + 1) * sizeof(wchar_t));
	memset(result, 0, (textlen + 1) * sizeof(wchar_t));
	MultiByteToWideChar(uAcp, 0, strTemp, -1, (LPWSTR)result, textlen);
	return result;
}


void CMFCFTPClientDlg::OnBnClickedBnTest()
{
	// TODO: 在此添加控件通知处理程序代码
	const char* strA = "a宽字符";
	CStringW strU; // 注意CString的构造函数不支持转码
	strU = strA; // CString 赋值操作符会进行转码

	char strA2[16];
	strcpy_s(strA2, strA);
	CStringW strU2;
	strU2 = strA2;

	

	printf("\n\n test mbcs to wchar:len_a=%d len_w=%d\n", strlen(strA),
		strU.GetLength());
	dump_memory("strA", strA, strlen(strA));
//	dump_memory("strU", strU.GetBuffer(), strU.GetLength() * sizeof(wchar_t));
//	strU.ReleaseBuffer();

	dump_memory("strA2", strA2, strlen(strA2));
//	dump_memory("strU2", strU2.GetBuffer(), strU2.GetLength() * sizeof(wchar_t));
//	strU2.ReleaseBuffer();

	const wchar_t* strW = L"a宽字符";
	CStringA strWA; // 注意CString的构造函数不支持转码
	strWA = strW; // CString 赋值操作符会进行转码

	wchar_t strW2[16];
	wcscpy_s(strW2, strW);
	CStringA strWA2;
	strWA2 = strW2;

	printf("\n\n test wchar to mbcs:len_a=%d len_w=%d\n", wcslen(strW),
		strWA.GetLength());
//	dump_memory("strW", strW, wcslen(strW) * sizeof(wchar_t));
	dump_memory("strWA", strWA.GetBuffer(), strWA.GetLength());
	strWA.ReleaseBuffer();

//	dump_memory("strW2", strW2, wcslen(strW2) * sizeof(wchar_t));
	dump_memory("strWA2", strWA2.GetBuffer(), strWA2.GetLength());
	strWA2.ReleaseBuffer();
	
	CStringA strA3 = "新建文件夹";
	dump_memory("strA3", strA3.GetBuffer(), strA3.GetLength());
	strA3.ReleaseBuffer();
	UTF8toANSI(strA3);
	dump_memory("strA3toANSI", strA3.GetBuffer(), strA3.GetLength());
	strA3.ReleaseBuffer();
}

void dump_memory(const char * strHead, const char* strBody,int nNum)
{
	printf("dump %s:\n",strHead);
	int i = 0;
	while (i < nNum)
	{
		printf("%02x ",(unsigned char)strBody[i]);
		i++;
	}
	printf("\n");
}

void CMFCFTPClientDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码

	//printf("Hello MFC world!\n"); 
	//printf("Hello MFC world!\n"); 
	printf("Hello MFC world!\n");

	//system("pause");
	
	CDialogEx::OnOK();
}

//UTF8转ANSI
void UTF8toANSI(CStringA& strUTF8)
{
	//获取转换为多字节后需要的缓冲区大小，创建多字节缓冲区
	UINT nLen = MultiByteToWideChar(CP_UTF8, NULL, strUTF8, -1, NULL, NULL);
	WCHAR* wszBuffer = new WCHAR[nLen + 1];
	nLen = MultiByteToWideChar(CP_UTF8, NULL, strUTF8, -1, wszBuffer, nLen);
	wszBuffer[nLen] = 0;

	nLen = WideCharToMultiByte(936, NULL, wszBuffer, -1, NULL, NULL, NULL, NULL);
	CHAR* szBuffer = new CHAR[nLen + 1];
	nLen = WideCharToMultiByte(936, NULL, wszBuffer, -1, szBuffer, nLen, NULL, NULL);
	szBuffer[nLen] = 0;

	strUTF8 = szBuffer;
	//清理内存  
	delete[]szBuffer;
	delete[]wszBuffer;
	
}

//ANSI转UTF8
void ANSItoUTF8(CStringA& strAnsi)
{
	//获取转换为宽字节后需要的缓冲区大小，创建宽字节缓冲区，936为简体中文GB231
	UINT nLen = MultiByteToWideChar(936, NULL, strAnsi, -1, NULL, NULL);
	WCHAR* wszBuffer = new WCHAR[nLen + 1];
	nLen = MultiByteToWideChar(936, NULL, strAnsi, -1, wszBuffer, nLen);
	wszBuffer[nLen] = 0;

	nLen = WideCharToMultiByte(CP_UTF8, NULL, wszBuffer, -1, NULL, NULL, NULL, NULL);
	CHAR* szBuffer = new CHAR[nLen + 1];
	nLen = WideCharToMultiByte(CP_UTF8, NULL, wszBuffer, -1, szBuffer, nLen, NULL, NULL);
	szBuffer[nLen] = 0;

	strAnsi = szBuffer;
	//清理内存  
	delete[]szBuffer;
	delete[]wszBuffer;

}

void CMFCFTPClientDlg::OnBnClickedBnTest1()
{
	// TODO: 在此添加控件通知处理程序代码
	// 参考来源：https://blog.csdn.net/arau_sh/article/details/2971496
	
	// NOTE: use s1._Bx._Buf to see the memory
	// 对上一行的理解，可参考：https://blog.csdn.net/m0_74722801/article/details/136825127
	std::string s0("蔡"); // b2 cc 00
	OutputDebugStringA(s0.c_str());
	printf(s0.c_str());

	std::wstring s1(L"蔡"); // b2 00 cc 00 00 00    _UNICODE & _MBCS：21 85 00 00

	OutputDebugStringW(s1.c_str());
	wprintf(s1.c_str());    //CRT的wprintf只支持MBCS编码的字符串，而不能是UNICODE编码的字符串

	// START: compile with  _UNICODE///
#ifdef _UNICODE
	CString s2("A"); // 41 00 00 00
	
	CString s3(L"A"); // 41 00 00 00
	
	CString s4(_T("A")); // 41 00 00 00
	
	CString s5("蔡 "); // 21 85 00 00
	
	CString s6(L"蔡 "); // b2 00 cc 00 00 00    _UNICODE：21 85 00 00 
	
	CString s7(_T("蔡 ")); // b2 00 cc 00 00 00     _UNICODE：21 85 00 00 
#endif // _UNICODE
	// END: compile with _UNICODE ///
	
	// START: compile with _MBCS ///
#ifdef _MBCS
	CString s2("A"); // 41 00
	
	CString s3(L"A"); // 41 00
	
	CString s4(_T("A")); // 41 00
	
	CString s5("蔡"); // b2 cc 00
	
	CString s6(L"蔡"); // 32 a8 ac 00       _MBCS： b2 cc 00          
	
	CString s7(_T("蔡")); // b2 cc 00       _MBCS： b2 cc 00
	
#endif // _MBCS
	// END: compile with _MBCS ///
}


void CMFCFTPClientDlg::OnBnClickedBnTest2()
{
	// TODO: 在此添加控件通知处理程序代码
	CStringA strA("新建文本文件");

	//UTF8toANSI(strA);
	ANSItoUTF8(strA);

	CStringA strB("鏂板缓鏂囨湰鏂囦欢");

	UTF8toANSI(strB);
	//ANSItoUTF8(strB);
}
